MODULE SampleCPX;
(*
 * ein etwas komplexeres Beispiel f�r die CPX-Programmierung.
 *
 * Folgendes wird demonstriert:
 *		- prinzipielles Dialog-Handling
 *		- Slider-Verwaltung
 *		- Popup-Verwaltung
 *		- Datensegment und Daten sichern
 *		- Tastaturbedienbarkeit
 *		- Verwaltung mehrerer Objektb„ume
 *		- Embedding einer gr”žeren Resource-Datei
 *)

IMPORT AES, TOS, CPX, evnt, graf,objc, RSC, rsCPX, Str;
FROM SYSTEM IMPORT ADR, ADDRESS;

TYPE
	tIt = ARRAY[0..11] OF CHAR;
	tMI = ARRAY[0..4] OF tIt;

	tpSave = POINTER TO tSave;
	tSave = RECORD
		cur_item,
		vcur_item,
		hcur_item: SHORTINT;
	END;

CONST
	AAAA = 0;
	INIT_VALUE = 6;

	NUM_ITEMS = 5;

	VIS_ITEMS = 10;
	MAX_ITEMS = 50;
	MIN_ITEMS = 0;

	menu_items = tMI{
	 "A. Alich   ",
	 "J. Reiž    ",
	 "C. Sprenger",
	 "T. Uhl     ",
	 "= MoSys GbR"};

VAR
	Save: tSave;

	blanks: ARRAY[0..4],[0..30] OF CHAR;
	blank:	ARRAY[0..4] OF ADDRESS;

	NULLFUNC: PROC;

	vcur_text,
	hcur_text: ARRAY[0..3] OF CHAR;
	Main,
	Help,
	Tree: objc.tpTree;

PROCEDURE initialize();
BEGIN
	WITH CPX.pXCPB^ DO
		Save := tpSave(TOS.DATA)^;

		Main^[RSC.POPUP].tedinfo^.ptext := ADR(menu_items)
		 + ORD(Save.cur_item*SIZE(menu_items[0]));

		vcur_text := FORM(Save.vcur_item);
		Main^[RSC.SLIDEV].tedinfo^.ptext := ADR(vcur_text);
		Sl_y(Main, RSC.BASEV, RSC.SLIDEV, Save.vcur_item,
			MAX_ITEMS, MIN_ITEMS, NULLFUNC);
		Sl_size(Main, RSC.BASEV, RSC.SLIDEV, MAX_ITEMS-MIN_ITEMS+1,
			VIS_ITEMS, CPX.Vertical, 16);

		hcur_text := FORM(Save.hcur_item);
		Main^[RSC.SLIDEH].tedinfo^.ptext := ADR(hcur_text);
		Sl_x(Main, RSC.BASEH, RSC.SLIDEH, Save.hcur_item,
			MIN_ITEMS, MAX_ITEMS, NULLFUNC);
		Sl_size(Main, RSC.BASEH, RSC.SLIDEH, MAX_ITEMS-MIN_ITEMS+1,
			VIS_ITEMS, CPX.Horizontal, 16);
	END
END initialize;

PROCEDURE Pop_Handle(Tree: objc.tpTree;
									 button: SHORTINT;
										items: ARRAY OF tIt;
								num_items: SHORTINT;
						 default_item: SHORTINT;
								font_size: SHORTINT): SHORTINT;
VAR
	butn, world: AES.tRect;
	i: SHORTINT;
BEGIN
	butn := Tree^[button].pos;
	objc.offset(Tree,button,butn.x,butn.y);
	world := Tree^[0].pos;
	objc.offset(Tree,0,world.x,world.y);

	FOR i:=0 TO num_items-1 DO
		blanks[i] := '  ';
		Str.Concat(blanks[i], items[i]);
		Str.Concat(blanks[i], '  ');
		blank[i] := ADR(blanks[i])
	END;
	RETURN CPX.pXCPB^.Popup(ADR(blank), num_items, default_item, font_size,
		butn, world)
END Pop_Handle;

(*$E+*)
PROCEDURE VDraw();
VAR
	rect: AES.tRect;
BEGIN
	vcur_text := FORM(Save.vcur_item);
	rect := Tree^[RSC.SLIDEV].pos;
	objc.offset(Tree,RSC.SLIDEV,rect.x,rect.y);
	objc.draw(Tree,RSC.SLIDEV,16,rect);
END VDraw;

PROCEDURE HDraw();
VAR
	rect: AES.tRect;
BEGIN
	hcur_text := FORM(Save.hcur_item);
	rect := Tree^[RSC.SLIDEH].pos;
	objc.offset(Tree,RSC.SLIDEH,rect.x,rect.y);
	objc.draw(Tree,RSC.SLIDEH,16,rect);
END HDraw;
(*$E=*)

PROCEDURE Redraw(VAR new: objc.tpTree);
VAR
	rect: AES.tRect;
	draw: AES.tpRect;
BEGIN
	WITH CPX.pXCPB^ DO
		new^[0].pos := Tree^[0].pos;
		Tree := new;
		objc.offset(Tree,0,rect.x,rect.y);
		draw := GetFirstRect(rect);
		WHILE draw#NIL DO
			objc.draw(Tree,0,16,draw^);
			draw := GetNextRect();
		END
	END
END Redraw;

PROCEDURE handle_button(button: SHORTINT; VAR msg: evnt.tMsg): BOOLEAN;
VAR
	click_flag: BOOLEAN;
	quit: BOOLEAN;
	ox,oy,obj: SHORTINT;
	rect: AES.tRect;
	mk: CPX.tMRets;
	mf: graf.tMForm;
BEGIN
	WITH CPX.pXCPB^ DO
		quit := FALSE;
		click_flag := (button<-1);
		IF click_flag THEN
			button := SHORTINT(BITSET(button)*{0..14});
		END;
		IF button=-1 THEN
			CASE msg.type OF
			|evnt.Close,	 (* AC_CLOSE -> Cancel *)
			 evnt.Closed:  (* WM_CLOSED -> Ok *)
				IF msg.type=evnt.Closed THEN
					tpSave(TOS.DATA)^ := Save
				END;
				quit := TRUE
			|evnt.CT_Key:
				IF Tree=Main THEN
					IF msg.key.scan=CHR(62H) THEN (* HELP *)
						Redraw(Help)
					ELSIF msg.key.scan=CHR(61H) THEN (* UNDO *)
						quit := TRUE
					END
				END
			ELSE
			END
		ELSIF Tree=Main THEN
			CASE button OF
			|RSC.SAVE:
				tpSave(TOS.DATA)^ := Save;
				IF XGen_Alert(CPX.SaveDefaults)
				& ~CPX_Save(TOS.DATA,SIZE(Save)) THEN
					VOID(XGen_Alert(CPX.FileErr))
				END;
				objc.change(Tree,RSC.SAVE,Tree^[0].pos,{},TRUE);
			|RSC.CANCEL,
			 RSC.QUIT:
				IF button=RSC.QUIT THEN
					tpSave(TOS.DATA)^ := Save
				END;
				quit := TRUE;
				EXCL(Tree^[button].state,objc.Selected)
			|RSC.HELP:
				EXCL(Tree^[RSC.HELP].state,objc.Selected);
				Redraw(Help)
			|RSC.POPUP:
				obj := Pop_Handle(Tree, RSC.POPUP, menu_items, NUM_ITEMS, Save.cur_item, objc.SystemFont);
				IF obj#-1 THEN
					Save.cur_item := obj;
		(*			Tree^[RSC.POPUP].tedinfo^.ptext := ADR(menu_items[cur_item]);*)
					Tree^[RSC.POPUP].tedinfo^.ptext := ADR(menu_items)
					 + ORD(Save.cur_item*SIZE(menu_items[0]));
				END;
				EXCL(Tree^[RSC.POPUP].state,objc.Selected);
				rect := Tree^[RSC.POPUP].pos;
				objc.offset(Tree, RSC.POPUP, rect.x, rect.y);
				objc.draw(Tree, RSC.POPUP, 16, rect);
			|RSC.UP:
				Sl_arrow(Tree,RSC.BASEV, RSC.SLIDEV, RSC.UP, -1, MAX_ITEMS, MIN_ITEMS,
					Save.vcur_item, CPX.Vertical, VDraw)
			|RSC.DOWN:
				Sl_arrow(Tree,RSC.BASEV, RSC.SLIDEV, RSC.DOWN, 1, MAX_ITEMS, MIN_ITEMS,
					Save.vcur_item, CPX.Vertical, VDraw)
			|RSC.BASEV:
				graf.mkstate(mk.x,mk.y,mk.buttons,mk.kstate);
				objc.offset(Tree,RSC.SLIDEV,ox,oy);
				IF mk.y<oy THEN ox := -VIS_ITEMS ELSE ox := VIS_ITEMS END;
				Sl_arrow(Tree,RSC.BASEV, RSC.SLIDEV, -1, ox, MAX_ITEMS, MIN_ITEMS,
					Save.vcur_item, CPX.Vertical, VDraw)
			|RSC.SLIDEV:
				MFsave(CPX.Save,mf);
				graf.mouseform(graf.FlatHand);
				Sl_dragy(Tree, RSC.BASEV, RSC.SLIDEV, MAX_ITEMS, MIN_ITEMS,
					Save.vcur_item, VDraw);
				MFsave(CPX.Restore,mf);
			|RSC.LEFT:
				Sl_arrow(Tree,RSC.BASEH, RSC.SLIDEH, RSC.LEFT, -1, MIN_ITEMS, MAX_ITEMS,
					Save.hcur_item, CPX.Horizontal, HDraw)
			|RSC.RIGHT:
				Sl_arrow(Tree,RSC.BASEH, RSC.SLIDEH, RSC.RIGHT, 1, MIN_ITEMS, MAX_ITEMS,
					Save.hcur_item, CPX.Horizontal, HDraw)
			|RSC.BASEH:
				graf.mkstate(mk.x,mk.y,mk.buttons,mk.kstate);
				objc.offset(Tree,RSC.SLIDEH,ox,oy);
				IF mk.x<ox THEN oy := -VIS_ITEMS ELSE oy := VIS_ITEMS END;
				Sl_arrow(Tree,RSC.BASEH, RSC.SLIDEH, -1, oy, MIN_ITEMS, MAX_ITEMS,
					Save.hcur_item, CPX.Horizontal, HDraw)
			|RSC.SLIDEH:
				MFsave(CPX.Save,mf);
				graf.mouseform(graf.FlatHand);
				Sl_dragx(Tree, RSC.BASEH, RSC.SLIDEH, MIN_ITEMS, MAX_ITEMS,
					Save.hcur_item, HDraw);
				MFsave(CPX.Restore,mf);
			ELSE
			END;
		ELSIF Tree=Help THEN
			IF button=RSC.HOK THEN
				EXCL(Tree^[RSC.HOK].state,objc.Selected);
				Redraw(Main)
			END
		END;
	END;
	RETURN quit
END handle_button;

(*$E+*)(*$K+*)
PROCEDURE cpx_call (VAR work: AES.tRect): SHORTINT;
VAR
	button: SHORTINT;
	quit: BOOLEAN;
	msg: evnt.tMsg;
BEGIN
	WITH Main^[0].pos DO x := work.x; y := work.y; END;
	WITH Help^[0].pos DO x := work.x; y := work.y; END;
	initialize();
	Tree := Main;
	objc.draw (Tree, 0, 8, work);
	quit := FALSE;
	REPEAT
		button := CPX.pXCPB^.Xform_do (Tree, 0, msg);
		quit := handle_button(button, msg)
	UNTIL quit;
	CPX.Terminate;
	RETURN 0
END cpx_call;
(*$E=*)(*$K=*)

BEGIN
	LONGCARD(NULLFUNC) := 0;
	WITH CPX.pXCPB^ DO
		IF booting # 0 THEN
			CPX.Return (CPX.tpCpxInfo(1))
		END;
		IF SkipRshFix = 0 THEN
			rsCPX.relocate(RSC.Data,RSC.Trees);
			Main := RSC.Trees^[0];
			Help := RSC.Trees^[1]
		END;
		CPX.CpxInfo.cpx_call := cpx_call;
		CPX.Return (ADR (CPX.CpxInfo))
	END;
END SampleCPX.
		
	
	